#include "stdafx.h"
#include "./io/io3ds.h"
#include "./material.h"

Material::Material()
{

}

Material::~Material()
{

}

void Material::LoadBy3dsFile(Lib3dsFile* pFile)
{
	Lib3dsMaterial* p3dsMaterial = NULL;

	for (int i = 0; i < pFile->nmaterials; ++i)
	{
		p3dsMaterial = pFile->materials[i];

		unsigned int texid = 0;

		if (p3dsMaterial->texture1_map.name[0])
		{
			//with bitmap

			ImageData imagedata = GetImageData(p3dsMaterial->texture1_map.name);
			if (imagedata.bSucceeded)
			{
				texid = LoadBitmapTexture(imagedata, p3dsMaterial);
			}
			imagedata.ReleaseBuffer();
		}
		else
		{
			//just color
			texid = LoadColorTexture(p3dsMaterial);
		}

		m_datalist.push_back(texid);
	}
}

void Material::LoadByMaterial(Material& material)
{
	MaterialListIter iter;
	for (iter = material.m_datalist.begin(); iter != material.m_datalist.end(); ++iter)
	{
		m_datalist.push_back(*iter);
	}
}

void Material::Render(int texid)
{
	if (static_cast<size_t>(texid) >= m_datalist.size())
	{
		return;
	}

	glBindTexture(GL_TEXTURE_2D, m_datalist[texid]);
}

ImageData Material::GetImageData(string strJpegPath)
{
	ImageData data;

	size_t jpegsize = IO3ds::GetInstance().ReadFile(strJpegPath, NULL, 0);
	byte* buffer = new byte[jpegsize];

	size_t rb = IO3ds::GetInstance().ReadFile(strJpegPath, buffer, jpegsize);
	if (rb != jpegsize)
	{
		data.bSucceeded = false;
		return data;
	}

	JpegDecoder decoder(buffer, rb);
	data = decoder.GetImageData();

	delete[] buffer;
	return data;
}

unsigned int Material::LoadBitmapTexture(ImageData data, Lib3dsMaterial* p3dsMaterial)
{
	GLuint texid = 0;

	glGenTextures(1, &texid);
	glBindTexture(GL_TEXTURE_2D, texid);

	glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	gluBuild2DMipmaps(GL_TEXTURE_2D, 4, data.nWidth, data.nHeight, GL_RGBA, GL_UNSIGNED_BYTE, data.pBuffer);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glMaterialfv(GL_FRONT, GL_AMBIENT, p3dsMaterial->ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, p3dsMaterial->diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, p3dsMaterial->specular);

	float s = pow(2, 10.0 * p3dsMaterial->shininess);

	if (s > 128.0)
	{
		s = 128.0;
	}

	glMateriali(GL_FRONT, GL_SHININESS, s);
	//glMateriali(GL_FRONT, GL_SHININESS, 128);

	return texid;
}

unsigned int Material::LoadColorTexture(Lib3dsMaterial* p3dsMaterial)
{
	GLuint texid = 0;

	glGenTextures(1, &texid);
	glBindTexture(GL_TEXTURE_2D, texid);

	glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glMaterialfv(GL_FRONT, GL_AMBIENT, p3dsMaterial->ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, p3dsMaterial->diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, p3dsMaterial->specular);

	float s = pow(2, 10.0 * p3dsMaterial->shininess);

	if (s > 128.0)
	{
		s = 128.0;
	}

	glMateriali(GL_FRONT, GL_SHININESS, s);

	return texid;
}